/*
	This file is part of Vajolet.

    Vajolet is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Vajolet is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Vajolet.  If not, see <http://www.gnu.org/licenses/>
*/
#include <iostream>
#include "move.h"
#include "board.h"
#include "movegen.h"
#include "data.h"
#include "bitops.h"

score Move::SEEsign(){

	if(Board::PIECESCORE[board.square[to]%Board::emptyBitmap]>=Board::PIECESCORE[board.square[from]%Board::emptyBitmap]){
	//if((board.square[to]%Board::emptyBitmap)<=(board.square[from]%Board::emptyBitmap)){ // fa perdere un sacco di punti 
		return 1;
	}
	return SEE();
}


//#define VERBOSE_SEE
score Move::SEE(){

	if(SEEscore != VALUE_NOT_CACHED){
		return SEEscore;
	}
	//	===========================================================================
	//  This is a bitmap implementation of SEE (Static Exchange Evaluator), 
	//	Captures that don't gain material are discarded during the quiescence search.
	//	SEE speeds up the search in two ways: 
	//	1) not all captures are searched, as in MVV/LVA
	//	2) move ordering of captures is improved
	//  there is no check for captures that leave the king in check 
	//	===========================================================================


	bitMap attackersAndDefender;
	bitMap removedAttacker=0;
	bitMap remainingAttacker;
	int attackedPieceVal=0;
	int color= board.nextMove;
	int materialGains[50];
	materialGains[0]=0;
	materialGains[1]=0;
	int promo=promotion;// promotion to
	bool fEnpassant=(flags==Move::fenpassant);
	bool fpromo=(flags==Move::fpromotion);

	// imposto il primo attaccante
	int mFrom=from;
	int mTo=to;

	//numero catture effettuate
	int nrCapt=0;

	if(fEnpassant){
		int localTo= mTo;
		if(color){
			localTo+=8;
		}else{
			localTo-=8;
		}
		removedAttacker|= BITSET[localTo];
	}

#ifdef VERBOSE_SEE
	std::cout << "=== START OF SEE === " << std::endl; 
	board.display();
	display(); 
	std::cout << std::endl; 
#endif
	attackersAndDefender = board.getAttackersAndDefenders(to);
	attackersAndDefender |= board.getXraySliderAttackersAndDefenders(to,removedAttacker); // utile in caso di enpassant
	remainingAttacker=attackersAndDefender;

	attackedPieceVal=Board::PIECESCORE[board.square[mTo]%Board::emptyBitmap];

	if(fEnpassant){
		attackedPieceVal=Board::PIECESCORE[Board::whitePawns];
		fEnpassant=false;
	}
	while(remainingAttacker){
		nrCapt++;
	#ifdef VERBOSE_SEE
		std::cout << " attacker from " << char(mFrom%8+'a') << char(mFrom/8+'1')<<std::endl; 
	#endif
	

		materialGains[nrCapt] = -materialGains[nrCapt - 1]+attackedPieceVal;

		// remember the value of the moving piece because this is going to be captured next:
		attackedPieceVal = Board::PIECESCORE[board.square[mFrom]%Board::emptyBitmap];

		
	
		// if it was a promotion, we need to add this into materialgains and attackedpieceval: 
		if (fpromo)
		{
			score t=Board::PIECESCORE[Board::whiteQueens+promo]-Board::PIECESCORE[Board::whitePawns];
			materialGains[nrCapt] += t;
			attackedPieceVal += t;
		}
		removedAttacker|=BITSET[mFrom];
		attackersAndDefender |= board.getXraySliderAttackersAndDefenders(to,removedAttacker);
		remainingAttacker=attackersAndDefender & ~removedAttacker;
	
		
		color=!color;
		fpromo=false;
		promo=0; // promotion to Queen
		//reveal new attacker
		if(remainingAttacker){
			if(color){// tocca al nero
				if  (RANKS[mTo] != 0 && (board.boards[Board::blackPawns] & remainingAttacker))   mFrom = firstOne(board.boards[Board::blackPawns] & remainingAttacker);
				else if (board.boards[Board::blackKnights] & remainingAttacker) mFrom = firstOne(board.boards[Board::blackKnights] & remainingAttacker);
				else if (board.boards[Board::blackBishops] & remainingAttacker) mFrom = firstOne(board.boards[Board::blackBishops] & remainingAttacker);
				else if (board.boards[Board::blackRooks] & remainingAttacker)   mFrom = firstOne(board.boards[Board::blackRooks] & remainingAttacker);
				else if  (RANKS[mTo] == 0 && (board.boards[Board::blackPawns] & remainingAttacker)){ mFrom = firstOne(board.boards[Board::blackPawns] & remainingAttacker);fpromo=true;}
				else if (board.boards[Board::blackQueens] & remainingAttacker)  mFrom = firstOne(board.boards[Board::blackQueens] & remainingAttacker);
				// king can only capture if there is no opponent attacker left
				else if ((board.boards[Board::blackKing] & remainingAttacker) && !(remainingAttacker & board.boards[Board::whitePieces])) mFrom = firstOne(board.boards[Board::blackKing]);
				else break;
			}else{//tocca al bianco
				if  (RANKS[mTo] != 7 && (board.boards[Board::whitePawns] & remainingAttacker))   mFrom = firstOne(board.boards[Board::whitePawns] & remainingAttacker);
				else if (board.boards[Board::whiteKnights] & remainingAttacker) mFrom = firstOne(board.boards[Board::whiteKnights] & remainingAttacker);
				else if (board.boards[Board::whiteBishops] & remainingAttacker) mFrom = firstOne(board.boards[Board::whiteBishops] & remainingAttacker);
				else if (board.boards[Board::whiteRooks] & remainingAttacker)   mFrom = firstOne(board.boards[Board::whiteRooks] & remainingAttacker);
				else if  (RANKS[mTo] == 7 && (board.boards[Board::whitePawns] & remainingAttacker)){mFrom = firstOne(board.boards[Board::whitePawns] & remainingAttacker);fpromo=true;}
				else if (board.boards[Board::whiteQueens] & remainingAttacker)  mFrom = firstOne(board.boards[Board::whiteQueens] & remainingAttacker);
				// king can only capture if there is no opponent attacker left
				else if ((board.boards[Board::whiteKing] & remainingAttacker) && !(remainingAttacker & board.boards[Board::blackPieces])) mFrom = firstOne(board.boards[Board::whiteKing]);
				else break;
			}
		}

	}

//	===========================================================================
//	Start at the end of the capture sequence and use a Minimax-type procedure 
//	to calculate the SEE value of the first capture:
//	===========================================================================
	/*if(nrCapt==0){
		board.display();
		display();
	}*/

	while (nrCapt){
		if (materialGains[nrCapt] > -materialGains[nrCapt - 1]){
			materialGains[nrCapt - 1] = -materialGains[nrCapt];
		}
		nrCapt--;
	}

	#ifdef WINGLET_VERBOSE_SEEgo
		std::cout << "SEE value of this capture = " << materialgains[1] << std::endl << std::endl; 
	#endif
	SEEscore=materialGains[1];
	return (SEEscore);
}
